package com.hzncc.flowable_diboot.service.refundmanage.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.diboot.core.binding.Binder;
import com.diboot.core.holder.ThreadLocalHolder;
import com.diboot.iam.entity.IamUser;
import com.diboot.iam.util.IamSecurityUtils;
import com.diboot.tenant.service.IamTenantService;
import com.hzncc.flowable_diboot.entity.SalesGroupContent;
import com.hzncc.flowable_diboot.entity.refundmanage.RefundContract;
import com.hzncc.flowable_diboot.exception.BusinessException;
import com.hzncc.flowable_diboot.payment.vo.*;
import com.hzncc.flowable_diboot.service.SalesGroupContentService;
import com.hzncc.flowable_diboot.service.refundmanage.RefundCertItemService;
import com.hzncc.flowable_diboot.service.refundmanage.RefundContractService;
import com.hzncc.flowable_diboot.service.refundmanage.RefundRegisterService;
import com.hzncc.flowable_diboot.util.SapUtil;
import com.hzncc.flowable_diboot.vo.refundmanage.*;
import com.sap.conn.jco.JCoException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import com.diboot.core.util.S;
import com.diboot.core.service.impl.BaseServiceImpl;

import com.hzncc.flowable_diboot.entity.refundmanage.RefundCert;

import com.hzncc.flowable_diboot.mapper.refundmanage.RefundCertMapper;
import com.hzncc.flowable_diboot.service.refundmanage.RefundCertService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
* 退款凭证 相关Service实现类
* @author MyName
* @version 1.0
* @date 2024-11-12
* Copyright © MyCorp
*/
@Slf4j
@Service
public class RefundCertServiceImpl extends BaseServiceImpl<RefundCertMapper, RefundCert> implements RefundCertService {

    private static final String accountingPeriod = "10";

    private static final String certType = "DZ";

    @Resource
    private RefundRegisterService refundRegisterService;

    @Resource
    private RefundContractService refundContractService;

    @Resource
    private RefundCertItemService refundCertItemService;

    @Resource
    private SalesGroupContentService salesGroupContentService;

    @Resource
    private IamTenantService iamTenantService;

    @Resource
    private SapUtil sapUtil;

    @Override
    public RefundCertDetailVO genRefundCert(String refundRegisterId) {
        RefundRegisterDetailVO refundRegister = refundRegisterService.getViewObject(refundRegisterId, RefundRegisterDetailVO.class);
        return this.genRefundCert(refundRegister);
    }

    @Override
    public RefundCertDetailVO genRefundCert(RefundRegisterDetailVO refundRegister) {
        String year = String.valueOf(Year.now().getValue());//会计年度
        LocalDateTime now = LocalDateTime.now();
        RefundCertDetailVO refundCertDetailVO = new RefundCertDetailVO();
        refundCertDetailVO.setRefundRegisterId(refundRegister.getId()).setYear(year).setCertDate(now).setPostDate(now)
                .setAccountingPeriod(accountingPeriod).setCertType(certType)
                .setCertTitle(refundRegister.getCustomerName() + "退款").setCurrencyCode("CNY");

        refundCertDetailVO.setRefundRegister(refundRegister);
        List<RefundContractDetailVO> refundContractListVOS = refundRegister.getRefundContractDetailVOS();
//        LambdaQueryWrapper<RefundContract> refundContractQuery = new LambdaQueryWrapper<>();
//        refundContractQuery.eq(RefundContract::getRefundRegisterId, refundRegister.getId()).eq(RefundContract::isDeleted, 0);
//        List<RefundContract> refundContractList = refundContractService.getEntityList(refundContractQuery);
//        List<RefundContractDetailVO> refundContractListVOS = Binder.convertAndBindRelations(refundContractList, RefundContractDetailVO.class);
        // 成本中心
        refundCertDetailVO.setCostCenter(refundContractListVOS.stream().map(e -> e.getCostCenterLabel().getLabel()).collect(Collectors.joining(",")));
        // 销售员
        refundCertDetailVO.setSalesperson(refundContractListVOS.stream().map(RefundContractListVO::getSalerLabel).collect(Collectors.joining(",")));
        // 客户名称
        refundCertDetailVO.setCustomerName(refundContractListVOS.stream().map(RefundContractListVO::getSapCustomerName).collect(Collectors.joining(",")));
        // 销售部门
        refundCertDetailVO.setSalesDept(refundContractListVOS.stream().map(e -> e.getSalesAreaLabel().getLabel()).collect(Collectors.joining(",")));
        String dis = "";
        String contractCode = "";
        // 费用报销单 第一条来源回款登记 = 总账 其余合同收款 = 明细
        ArrayList<RefundCertItemListVO> refundCertItems = new ArrayList<>();
        // 回款登记 回款类型判断
        RefundCertItemListVO refundCertItem = new RefundCertItemListVO();
        if (S.equals(refundRegister.getRefundType(), "10") || S.equals(refundRegister.getRefundType(), "20")) {
            refundCertItem.setAccountCode("50");
            refundCertItem.setAccountTitle(S.equals(refundRegister.getRefundType(), "10") ? "1001000001" : refundRegister.getPaymentItem());
        } else {
            refundCertItem.setAccountCode("19");
            refundCertItem.setLedgerFlag(S.equals(refundRegister.getRefundType(), "30") ? "01" : S.equals(refundRegister.getRefundType(), "40") ? "02" : "");
            refundCertItem.setAssignmentCode(refundRegister.getBillNum());
        }
        refundCertItem.setBaseDate(refundRegister.getRefundTime());
        refundCertItem.setCurrencyAmount(refundRegister.getRefundAmount());
        refundCertItem.setReasonCode("A01");
        refundCertItem.setProjectText(refundContractListVOS.stream().map(RefundContractListVO::getSapCustomerName).collect(Collectors.joining(",")));
        refundCertItems.add(refundCertItem);
        for (RefundContractDetailVO refundContract : refundContractListVOS) {
            RefundCertItemListVO itemListVO = new RefundCertItemListVO();
            List<SapRefundContractDetailVO> sapRefundContractList = CollectionUtils.isEmpty(refundContract.getSapRefundContractList())?new ArrayList<>():refundContract.getSapRefundContractList();
            LambdaQueryChainWrapper<SalesGroupContent> query = salesGroupContentService.lambdaQuery().select(SalesGroupContent::getDis)
                    .eq(SalesGroupContent::getSapCustomerId, refundContract.getSapCustomerId()).eq(SalesGroupContent::getIsFreeze, "0");
            ThreadLocalHolder.setIgnoreInterceptor();
            List<SalesGroupContent> entityList = salesGroupContentService.getEntityList(query);
            for (SapRefundContractListVO sapRefundContractListVO : sapRefundContractList) {
                itemListVO.setAccountCode("09");
                itemListVO.setCurrencyAmount(refundContract.getCurrentRefundAmount());
                if (!entityList.isEmpty()) {
                    dis = !dis.contains(entityList.get(0).getDis()) ? dis + entityList.get(0).getDis() + "," : dis;
                    itemListVO.setLedgerFlag(S.equals(entityList.get(0).getDis(), "01") ? "0" : "A");
                } else {
                    throw new BusinessException("SAP客户无有效的销售组织目录");
                }
                contractCode = !contractCode.contains(sapRefundContractListVO.getContractCode()) ? contractCode + sapRefundContractListVO.getContractCode() + "," : contractCode;
                itemListVO.setAssignmentCode(sapRefundContractListVO.getContractCode());
                itemListVO.setBaseDate(refundContract.getRefundTime());
                itemListVO.setCustomerCode(refundContract.getSapCustomerCode());
                String projectTxt = refundContract.getSapCustomerName();
                itemListVO.setProjectText(projectTxt);
                itemListVO.setSalerId(refundContract.getSaler());
                itemListVO.setPaymentNote(S.isNotEmpty(sapRefundContractListVO.getContractCode()) ? sapRefundContractListVO.getContractCode() : refundContract.getSapCustomerName());
                itemListVO.setCustomerCode(refundContract.getSapCustomerCode());
                itemListVO.setCustomerName(refundContract.getSapCustomerName());
                refundCertItems.add(itemListVO);
            }
        }
        Binder.bindRelations(refundCertItems);
        refundCertDetailVO.setRefundCertItemList(refundCertItems);
        if (!contractCode.isEmpty()) {
            contractCode = contractCode.substring(0, contractCode.length() - 1);
        }
        if (!dis.isEmpty()) {
            dis = dis.substring(0, dis.length() - 1).replaceAll("01", "集团外客户").replaceAll("02", "集团内客户");
        }
        refundCertDetailVO.setContractCode(contractCode);
        refundCertDetailVO.setDis(dis);
        return refundCertDetailVO;
    }

    @Override
    @Transactional
    public Boolean createRefundCert(RefundCertDetailVO refundCertDetailVO,boolean revokeCert) throws JCoException {
        // 构建sap接口参数
        Map<String, Object> param = new HashMap<>();
        param.put("BUKRS", iamTenantService.getEntity(IamSecurityUtils.getCurrentTenantId()).getOaNum()); // 公司代码
        param.put("GJAHR", refundCertDetailVO.getPostDate().format(DateTimeFormatter.ofPattern("yyyy"))); // 会计年度
        param.put("BLDAT", refundCertDetailVO.getPostDate().format(DateTimeFormatter.ofPattern("yyyyMMdd"))); // 凭证日期
        param.put("BUDAT", refundCertDetailVO.getPostDate().format(DateTimeFormatter.ofPattern("yyyyMMdd"))); // 过账日期
        param.put("MONAT", refundCertDetailVO.getPostDate().format(DateTimeFormatter.ofPattern("MM"))); // 会计期间
        param.put("BLART", "DZ"); // 凭证类型
        param.put("BKTXT", refundCertDetailVO.getCertTitle()); // 凭证抬头
        IamUser currentUser = IamSecurityUtils.getCurrentUser();
        param.put("USNAM", currentUser.getRealname()); // 用户名
        param.put("WAERS", "CNY"); // 货币码
        param.put("XBLNR", null); // 凭证号 todo 暂不知道来源
        List<RefundCertItemListVO> refundCertItemList = refundCertDetailVO.getRefundCertItemList();
        List<Map<String, Object>> sapRefundCertDetailVOList = refundCertItemList.stream().map(item -> {
            Map<String, Object> map = new HashMap<>();
            map.put("BSCHL", item.getAccountCode()); //记账代码
            map.put("HKONT", item.getAccountTitle()); // 总账科目
            map.put("KOSTL", item.getCostCenter()); // 成本中心
            map.put("WRBTR", item.getCurrencyAmount()); // 金额
            map.put("UMSKZ", item.getLedgerFlag()); // 特殊总账标识
            map.put("ZUONR", item.getAssignmentCode()); // 分配编号
            item.setBaseDate(item.getBaseDate() == null ? LocalDateTime.now() : item.getBaseDate());
            map.put("ZFBDT", item.getBaseDate().format(DateTimeFormatter.ofPattern("yyyyMMdd"))); // 过账日期
            map.put("KUNNR", item.getCustomerCode()); // 客户代码
            map.put("SGTXT", item.getProjectText()); // 客户名称
            map.put("RSTGR", item.getReasonCode()); // 付款原因代码
            map.put("ZTEXT1", item.getSalerName()); // 员工姓名
            map.put("ZTEXT2", item.getSalerNum()); // 员工编号
            map.put("KIDNO", item.getPaymentNote()); // 付款参考
            return map;
        }).toList();
        // 调用SAP接口获取凭证号
        Map<String, String> res = sapUtil.refundCert("ZRFC_CRM_ACCOUNTING", param, sapRefundCertDetailVOList);
        if (S.equals(res.get("code"), "S")) {
            refundCertDetailVO.setSapCertCode(res.get("sapCertCode"));
            refundCertDetailVO.setSapPushStatus(2); // 成功
        } else {
            refundCertDetailVO.setSapResponseMsg(res.get("msg"));
            refundCertDetailVO.setSapPushStatus(1); // 失败
        }
        if(!revokeCert){
            this.createEntity(refundCertDetailVO);
            RefundRegisterListVO refundRegister = refundCertDetailVO.getRefundRegister();
            refundRegister.setId(refundCertDetailVO.getRefundRegisterId());
            if(2==refundCertDetailVO.getSapPushStatus()){
                refundRegister.setCerted("1");
            }else {
                refundRegister.setCerted("0");
            }
            refundRegisterService.updateEntity(refundRegister);
            refundCertItemList.forEach(item -> item.setRefundCertId(refundCertDetailVO.getId()));
            refundCertItemService.createEntities(refundCertItemList);
        }
        return true;


    }
}